#include <iostream>
#include <string>
#include <sstream>
#include <jsoncpp/json/json.h>

std::string serialize()
{
    std::cout << "serialize->\n";

    // 1. 将需要进行序列化的数据，存储在Json::Value 对象中
    Json::Value root;

    root["name"] = "张三";
    root["age"] = 20;                                   // 单参数构造 + 拷贝构造
    // Value &operator=(const Value &other);            // Value重载了[]和=，因此所有的赋值和获取数据都可以通过
    // Value& operator[](const std::string& key);       // 简单的⽅式完成 val["name"] = "xx";

    root["score"].append(80);                           // 添加数组元素val["score"].append(88);
    root["score"].append(80.5);
    root["score"].append(80.8);

    // 2. 实例化一个StreamWriterBuilder工厂类对象
    Json::StreamWriterBuilder swb;

    // 3. 通过这个StreamWriterBuilder工厂类对象生产一个StreamWirter类对象
    Json::StreamWriter *sw = swb.newStreamWriter();     // 后面要记得释放

    // 4. 使用StreamWriter对象，对Json::Value中存储的数据进行序列化
    std::stringstream ss;
    int ret = sw->write(root, &ss);
    if(ret != 0)
    {
        std:: cout << "serialize failed!\n";
        return "";
    }

    std::cout << ss.str() << std::endl;
    delete sw;
    return ss.str();
}

void deserialize(const std::string str)
{
    std::cout << "deserialize->\n";

    // 1. 实例化一个CharReaderBuilder工厂类对象
    Json::CharReaderBuilder crb;

    // 2. 使用CharReaderBuilder工厂类生产一个CharReader对象
    Json::CharReader *cr = crb.newCharReader();

    // 3. 定义一个Json::Value对象存储解析后的数据
    Json::Value root;
    std::string err;

    // 4. 使用CharReader对象进行json格式字符串str的反序列化
    // parse(char *start,  char *end,  Json::Value *val,  string *err);     // 这里的err是出错时返回的输出型参数
    bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
    if(ret == false)
    {
        std::cout << "deserialize failed!" << std::endl;
        exit(2);
    }

    // 5. 逐个元素去访问Json::Value中的数据
    std::cout << "姓名: " << root["name"].asString() << std::endl;
    std::cout << "年龄: " << root["age"].asInt() << std::endl;

    // json中数组遍历
    int sz = root["score"].size();
    for(int i = 0; i < sz; i++)
    {
        std::cout << "成绩: " << root["score"][i].asFloat() << std::endl;
    }

    delete cr;
}

int main()
{
    std::string str = serialize();
    deserialize(str);
    return 0;
}